package util;
/**
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;

import org.codehaus.plexus.util.IOUtil;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * @author thiagoepdc
 * @author Jonhnny Weslley - jonhnny@lsd.ufcg.edu.br
 *
 */
public class Ssh extends RemoteService<Ssh> {

	public static class Result {

		private final String output;
		private final int exitStatus;

		Result(String output, int exitCode) {
			this.output = output;
			exitStatus = exitCode;
		}

		public String getOutput() {
			return output;
		}

		public int getProcessExitStatus() {
			return exitStatus;
		}

	}

	public Result exec(String remoteCommand, Object... args) throws IOException {
		return exec(MessageFormat.format(remoteCommand, args));
	}

	public Result exec(String remoteCommand) throws IOException {
		
		Result result;
		InputStream out = null;
		InputStream err = null;

		try {

			Session session = createSession();
			session.connect();

			ChannelExec channel = (ChannelExec) session.openChannel("exec");
			channel.setCommand(remoteCommand);
			channel.setInputStream(null);
			channel.setErrStream(null);

			out = channel.getInputStream();
			err = channel.getExtInputStream();

			channel.connect();

			byte[] buffer = new byte[1024];
			StringBuffer output = new StringBuffer();

			while (true) {
				
				read(out, buffer, output);
				read(err, buffer, output);

				if (channel.isClosed()) {
					result = new Result(output.toString(), channel.getExitStatus());
					break;
				}
			}

			channel.disconnect();
			session.disconnect();

		} catch (JSchException e) {
			throw new IOException(e);

		} finally {
			IOUtil.close(out);
			IOUtil.close(err);
		}
		
		return result;
	}

	/**
	 *
	 * @param in
	 * @param buffer
	 * @param appendable
	 * @throws IOException
	 */
	private void read(InputStream in, byte[] buffer, Appendable appendable)
			throws IOException {
		while (in.available() > 0) {
			int i = in.read(buffer, 0, 1024);
			appendable.append(new String(buffer, 0, i));
			if (i < 0) {
				break;
			}
		}
	}

	public static Ssh to(String hostname) {
		return new Ssh().at(hostname);
	}

}
